package JavaEE.ManyThread6;
import java.util.*;
import java.util.concurrent.BlockingQueue;
/*
 模拟实现阻塞队列
 1. 阻塞队列满时,t1(生产者)进入阻塞状态,等待t2(消费者)消耗队列(唤醒).
 2. 阻塞队列空时,t2(消费者)进入阻塞状态,等待t1(生产者)填充队列(唤醒).
 */
public class Demo3 {
    public static void main(String[] args) throws InterruptedException{
        MyBlockingQueue queue = new MyBlockingQueue(100);
        // 生产者消费者模型
        Thread t1 = new Thread(() -> {
            int num = 0;
            try{
                while(true){
                    queue.put(num);
                    System.out.println("t1线程生产了一个数字:" + num++);
                    Thread.sleep(1000);
                }
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        });
        Thread t2 = new Thread(() -> {
            try{
                while(true){
                    int num = queue.take();
                    System.out.println("t2线程消耗了一个数字:" + num);
                    Thread.sleep(1000);
                }
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}
// 模拟实现一个阻塞队列
class MyBlockingQueue{
    private static Object locker = new Object();
    private static int n = 0;
    private static int[] queue;
    private static int head = 0;
    private static int end = 0;
    private static int size = 0;

    public static void put(int num) throws InterruptedException{
        synchronized (locker) {
            // 如果队列已满,阻塞状态,等待take
            while(size == n) {
                locker.wait();
            }
            queue[end] = num;
            end++;
            // 循环数组,组成环
            if (end == n) {
                end = 0;
            }
            size++;
            locker.notify();
        }
    }
    public static int take() throws InterruptedException{
        synchronized (locker){
            while(size == 0){
                locker.wait();
            }
            int num = queue[head];
            head++;
            if(head == n){
                head = 0;
            }
            size--;
            locker.notify();
            return num;
        }
    }
    // 带参构造函数,表示队列大小
    public MyBlockingQueue(int n){
        this.n = n;
        queue = new int[n];
    }
}
